package com.huluobo.lib_base

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.ToastUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import java.io.File
import java.lang.Exception

/**
 *  Created by LC on 2025/5/23.
 */
abstract class BaseViewModel<uiIntent : UIIntent> : ViewModel() {

    //存放意图的管道(频道]),UNLIMITED 代表当前频道数量没有最小值
    private val _uiIntent = Channel<UIIntent> { Channel.UNLIMITED }

    //可变的状态,用于更新UI,默认值是读取中
    //由于是用private修饰的,不允许外部修改,所以需要对外暴露一个getter方法
    private var _state = MutableStateFlow<UIState>(UIState.OnLoading)
    val state: StateFlow<UIState>
        get() = _state

    //初始化
    init {
        viewModelScope.launch {
            _uiIntent.receiveAsFlow().collect {
                handleIntent(it)
            }
        }
    }

    //所有继承当前BaseViewModel的类,都需要实现该方法,来处理对应的意图
    //比如登录的Intent,需要处理登录的意图
    abstract fun handleIntent(it: UIIntent)

    //发送意图
    //当前页面需要有发送请求数据的时候,需要调用该方法,并传入一个意图
    fun sendIntent(intent: UIIntent) {
        viewModelScope.launch {
            _uiIntent.send(intent)
        }
    }

    //请求方法
    fun httpRequest(request: Flow<Res<Any>>, type: StateType = StateType.DEFAULT) {
        viewModelScope.launch {
            //将请求转换到子线程中运行
            request.flowOn(Dispatchers.IO)
                //捕获异常
                .catch {
                    ToastUtils.showLong("网络请求错误: ${it.message}")
                    Log.e("TagA", "网络请求错误:${it.message}")
                }.collect {
                    if (it.code == 0) {
                        _state.value = UIState.OnSuccess(it.data, type)
                    } else {
                        _state.value = UIState.OnError(it.msg)
                    }
                }
        }
    }

    fun httpRequestVideo(request: Flow<Res2<Any>>, type: StateType = StateType.DEFAULT) {
        viewModelScope.launch {
            request.flowOn(Dispatchers.IO)
                .catch {
                    Log.e("TagA", "error:${it.message}")
                }.collect {
                    if (it.code == 200) {
                        _state.value = UIState.OnSuccess(it.data, type)
                    } else {
                        _state.value = UIState.OnError(it.message)
                    }
                }
        }
    }

    //下载文件的方法
    fun download(url: String, file: File) {
        viewModelScope.launch {
            DownloadUtils.download(url, file)
                .flowOn(Dispatchers.IO)
                .catch {
                    Log.e("TagA", "下载错误:${it.message}")
                }.collect {
                    _state.value = it
                }
        }
    }

    //请求数据库的方法
    fun roomRequest(request: Flow<Any>, type: StateType = StateType.ROOM) {
        viewModelScope.launch {
            request.flowOn(Dispatchers.IO)
                .catch {
                    Log.e("TagA", "数据库错误:${it.message}")
                }.collect {
                    if (it != null) {
                        _state.value = UIState.OnSuccess(it, type)
                    } else {
                        _state.value = UIState.OnError("数据库查询错误,查询为空")
                    }
                }
        }
    }

    //当前的file代表的是一个文件夹,在kotlin或者android中,file不光可以代表是一个文件,也可以代表是一个文件夹
    fun scanFile(file: File) {
        viewModelScope.launch {
            try {
                //查找文件夹中所有的文件,形成一个list集合
                val files = file.listFiles()
                //声明一个集合,集合中的泛型是自己创建的数据类型,包含文件名和文件路径
                val list = mutableListOf<LocalFileEntity>()
                for (i in files) {
                    //循环添加文件夹中所有的文件到集合中
                    list.add(LocalFileEntity(i.name, i.absolutePath))
                }
                _state.value = UIState.OnSuccess(list)
            } catch (e: Exception) {
                _state.value = UIState.OnError(e.message.toString())
            }
        }
    }
}

//本地文件的实体类,文件名和文件路径
data class LocalFileEntity(val fileName: String, val filePath: String)